home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume10 / comobj.lisp / part06 < prev    next >
Encoding:
Internet Message Format  |  1987-08-01  |  44.8 KB

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v10i080:  Common Objects, Common Loops, Common Lisp, Part06/13
  5. Message-ID: <749@uunet.UU.NET>
  6. Date: 3 Aug 87 03:00:33 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 1325
  9. Approved: rs@uunet.UU.NET
  10.  
  11. Submitted-by: Roy D'Souza <dsouza%hplabsc@hplabs.HP.COM>
  12. Posting-number: Volume 10, Issue 80
  13. Archive-name: comobj.lisp/Part06
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 6 (of 13)."
  22. # Contents:  gfun-low.l test.l
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'gfun-low.l' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'gfun-low.l'\"
  26. else
  27. echo shar: Extracting \"'gfun-low.l'\" \(20567 characters\)
  28. sed "s/^X//" >'gfun-low.l' <<'END_OF_FILE'
  29. X;;;-*-Mode:LISP; Package:(PCL (LISP WALKER) 1000); Base:10; Syntax:Common-lisp -*-
  30. X;;;
  31. X;;; *************************************************************************
  32. X;;; Copyright (c) 1985 Xerox Corporation.  All rights reserved.
  33. X;;;
  34. X;;; Use and copying of this software and preparation of derivative works
  35. X;;; based upon this software are permitted.  Any distribution of this
  36. X;;; software or derivative works must comply with all applicable United
  37. X;;; States export control laws.
  38. X;;; 
  39. X;;; This software is made available AS IS, and Xerox Corporation makes no
  40. X;;; warranty about the software, its performance or its conformity to any
  41. X;;; specification.
  42. X;;; 
  43. X;;; Any person obtaining a copy of this software is requested to send their
  44. X;;; name and post office or electronic mail address to:
  45. X;;;   CommonLoops Coordinator
  46. X;;;   Xerox Artifical Intelligence Systems
  47. X;;;   2400 Hanover St.
  48. X;;;   Palo Alto, CA 94303
  49. X;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
  50. X;;;
  51. X;;; Suggestions, comments and requests for improvements are also welcome.
  52. X;;; *************************************************************************
  53. X;;;
  54. X
  55. X#|  To do:
  56. X
  57. Xfigure out bootstrapping issues
  58. X
  59. Xfix problems caused by make-iwmc-class-accessor
  60. X
  61. Xpolish up the low levels of iwmc-class, 
  62. X
  63. Xpolish up low levels of this and implement it for the 3600 then Lucid.
  64. X
  65. Xfix use of get-slot-using-class--class-internal
  66. X
  67. X|#
  68. X  ;;   
  69. X;;;;;; FUNCALLABLE INSTANCES
  70. X  ;;
  71. X
  72. X#|
  73. X
  74. XIn CommonLoops, generic functions are instances whose meta class is
  75. Xfuncallable-standard-class.  Instances with this meta class behave
  76. Xsomething like lexical closures in that they have slots, just like
  77. Xinstances with meta class standard-class, and are also funcallable.
  78. XWhen an instance with meta class funcallable-standard-class is
  79. Xfuncalled, the value of its function slot is called.
  80. X
  81. XIt is possible to implement funcallable instances in pure Common Lisp.
  82. XA simple implementation which uses lexical closures as the instances and
  83. Xa hash table to record that the lexical closures are funcallable
  84. Xinstances is easy to write.  Unfortunately, this implementation adds
  85. Xsuch significant overhead:
  86. X
  87. X   to generic-function-invocation (1 function call)
  88. X   to slot-access (1 function call)
  89. X   to class-of a generic-function (1 hash-table lookup)
  90. X
  91. Xthat it is too slo to be practical.
  92. X
  93. XInstead, PCL uses a specially tailored implementation for each common
  94. XLisp and makes no attempt to provide a purely portable implementation.
  95. XThe specially tailored implementations are based on each the lexical
  96. Xclosure's provided by that implementation and tend to be fairly easy to
  97. Xwrite.
  98. X
  99. X|#
  100. X
  101. X(in-package 'pcl)
  102. X
  103. X;;;
  104. X;;; The first part of the file contains the implementation dependent code
  105. X;;; to implement the low-level funcallable instances.  Each implementation
  106. X;;; must provide the following functions and macros:
  107. X;;; 
  108. X;;;    MAKE-FUNCALLABLE-INSTANCE-1 ()
  109. X;;;       should create and return a new funcallable instance
  110. X;;;
  111. X;;;    FUNCALLABLE-INSTANCE-P (x)
  112. X;;;       the obvious predicate
  113. X;;;
  114. X;;;    SET-FUNCALLABLE-INSTANCE-FUNCTION-1 (fin new-value)
  115. X;;;       change the fin so that when it is funcalled, the new-value
  116. X;;;       function is called.  Note that it is legal for new-value
  117. X;;;       to be copied before it is installed in the fin (the Lucid
  118. X;;;       implementation in particular does this).
  119. X;;;
  120. X;;;    FUNCALLABLE-INSTANCE-DATA-1 (fin data-name)
  121. X;;;       should return the value of the data named data-name in the fin
  122. X;;;       data-name is one of the symbols in the list which is the value
  123. X;;;       of funcallable-instance-data.  Since data-name is almost always
  124. X;;;       a quoted symbol and funcallable-instance-data is a constant, it
  125. X;;;       is possible (and worthwhile) to optimize the computation of
  126. X;;;       data-name's offset in the data part of the fin.
  127. X;;;       
  128. X
  129. X(defconstant funcallable-instance-data
  130. X         '(class wrapper static-slots dynamic-slots)
  131. X  "These are the 'data-slots' which funcallable instances have so that
  132. X   the meta-class funcallable-standard-class can store class, and static
  133. X   and dynamic slots in them.")
  134. X
  135. X#+Lucid
  136. X(progn
  137. X  
  138. X(defconstant funcallable-instance-procedure-size 50)
  139. X(defconstant funcallable-instance-flag-bit #B1000000000000000)
  140. X(defvar *funcallable-instance-trampolines* ()
  141. X  "This is a list of all the procedure sizes which were too big to be stored
  142. X   directly in a funcallable instance.  For each of these procedures, a
  143. X   trampoline procedure had to be used.  This is for metering information
  144. X   only.")
  145. X
  146. X(defun make-funcallable-instance-1 ()
  147. X  (let ((new-fin (lucid::new-procedure funcallable-instance-procedure-size)))
  148. X    ;; Have to set the procedure function to something for two reasons.
  149. X    ;;   1. someone might try to funcall it.
  150. X    ;;   2. the flag bit that says the procedure is a funcallable
  151. X    ;;      instance is set by set-funcallable-instance-function.
  152. X    (set-funcallable-instance-function
  153. X      new-fin
  154. X      #'(lambda (&rest ignore)
  155. X      (declare (ignore ignore))
  156. X      (error "Attempt to funcall a funcallable-instance without first~%~
  157. X                  setting its funcallable-instance-function.")))
  158. X    new-fin))
  159. X
  160. X(defmacro funcallable-instance-p (x)
  161. X  (once-only (x)
  162. X    `(and (lucid::procedurep ,x)
  163. X      (logand (lucid::procedure-ref ,x lucid::procedure-flags)
  164. X          funcallable-instance-flag-bit))))
  165. X
  166. X(defun set-funcallable-instance-function-1 (fin new-value)
  167. X  (unless (funcallable-instance-p fin)
  168. X    (error "~S is not a funcallable-instance"))
  169. X  (cond ((not (functionp new-value))
  170. X     (error "~S is not a function."))
  171. X    ((not (lucid::procedurep new-value))
  172. X     ;; new-value is an interpreted function.  Install a
  173. X     ;; trampoline to call the interpreted function.
  174. X     (set-funcallable-instance-function fin
  175. X                        (make-trampoline new-value)))
  176. X    (t
  177. X     (let ((new-procedure-size (lucid::procedure-length new-value))
  178. X           (max-procedure-size (- funcallable-instance-procedure-size
  179. X                      (length funcallable-instance-data))))
  180. X       (if (< new-procedure-size max-procedure-size)
  181. X           ;; The new procedure fits in the funcallable-instance.
  182. X           ;; Just copy the new procedure into the fin procedure,
  183. X           ;; also be sure to update the procedure-flags of the
  184. X           ;; fin to keep it a fin.
  185. X           (progn 
  186. X         (dotimes (i max-procedure-size)
  187. X           (setf (lucid::procedure-ref fin i)
  188. X             (lucid::procedure-ref new-value i)))
  189. X         (setf (lucid::procedure-ref fin lucid::procedure-flags)
  190. X               (logand funcallable-instance-flag-bit
  191. X                   (lucid::procedure-ref
  192. X                 fin lucid::procedure-flags)))
  193. X         new-value)
  194. X           ;; The new procedure doesn't fit in the funcallable instance
  195. X           ;; Instead, install a trampoline procedure which will call
  196. X           ;; the new procecdure.  First make note of the fact that we
  197. X           ;; had to trampoline so that we can see if its worth upping
  198. X           ;; the value of funcallable-instance-procedure-size.
  199. X           (progn
  200. X         (push new-procedure-size *funcallable-instance-trampolines*)
  201. X         (set-funcallable-instance-function
  202. X           fin
  203. X           (make-trampoline new-value))))))))
  204. X
  205. X
  206. X(defmacro funcallable-instance-data-1 (instance data)
  207. X  `(lucid::procedure-ref ,instance
  208. X             (- funcallable-instance-procedure-size
  209. X                (position ,data funcallable-instance-data))))
  210. X  
  211. X);dicuL+#
  212. X
  213. X;;;
  214. X;;; All of these Lisps (Xerox Symbolics ExCL KCL and VAXLisp) have the
  215. X;;; following in Common:
  216. X;;; 
  217. X;;;    - they represent their compiled closures as a pair of
  218. X;;;      environment and compiled function
  219. X;;;    - they represent the environment using a list or a vector
  220. X;;;    - I don't (YET) know how to add a bit to the damn things to
  221. X;;;      say that they are funcallable-instances and so I have to
  222. X;;;      use the last entry in the closure environment to do that.
  223. X;;;      This is a lose because that is much slower, I have to CDR
  224. X;;;      down to the last element of the environment.
  225. X;;;      
  226. X#+(OR Xerox Symbolics ExCL KCL (and DEC VAX))
  227. X(progn
  228. X
  229. X(defvar *funcallable-instance-marker* (list "Funcallable Instance Marker"))
  230. X
  231. X(defconstant funcallable-instance-closure-size 15)
  232. X
  233. X(defmacro lexical-closure-p (lc)
  234. X  #+Xerox         `(typep ,lc 'il:compiled-closure)
  235. X  #+Symbolics     `(si:lexical-closure-p ,lc)
  236. X  #+ExCL          `()
  237. X  #+KCL           `()
  238. X  #+(and DEC VAX) (once-only (lc)
  239. X            `(and (listp ,lc)
  240. X              (eq (car ,lc) 'system::%compiled-closure%))))
  241. X
  242. X(defmacro lexical-closure-env (lc)
  243. X  #+Xerox         `()
  244. X  #+Symbolics     `(si:lexical-closure-environment ,lc)
  245. X  #+ExCL          `()
  246. X  #+KCL           `()
  247. X  #+(and DEC VAX) `(caadr ,lc))
  248. X
  249. X(defmacro lexical-closure-env-size (env)
  250. X  #+Xerox         `()
  251. X  #+Symbolics     `(length ,env)
  252. X  #+ExCL          `()
  253. X  #+KCL           `()
  254. X  #+(and DEC VAX) `(array-dimension ,env 0))  
  255. X
  256. X(defmacro lexical-closure-env-ref (env index check) check
  257. X  #+Xerox         `()
  258. X  #+Symbolics     `(let ((env ,env))
  259. X             (dotimes (i ,index)
  260. X               (setq env (cdr env)))
  261. X             (car env))
  262. X  #+ExCL          `()
  263. X  #+KCL           `()
  264. X  #+(and DEC VAX) (once-only (env)
  265. X            `(and ,(or checkp
  266. X                   `(= (array-dimension ,env 0)
  267. X                   funcallable-instance-closure-size))
  268. X              (svref ,env 0))))
  269. X
  270. X(defmacro lexical-closure-env-set (env index new checkp) checkp
  271. X  #+Xerox         `()
  272. X  #+Symbolics     `(let ((env ,env))
  273. X             (dotimes (i ,index)
  274. X               (setq env (cdr env)))
  275. X             (setf (car env) ,new))
  276. X  #+ExCL          `()
  277. X  #+KCL           `()
  278. X  #+(and DEC VAX) (once-only (env)
  279. X            `(and ,(or checkp
  280. X                   `(= (array-dimension ,env 0)
  281. X                   funcallable-instance-closure-size))
  282. X              (setf (svref ,env ,index) ,new))))
  283. X
  284. X(defmacro lexical-closure-code (lc)
  285. X  #+Xerox         `()
  286. X  #+Symbolics     `(si:lexical-closure-function ,lc)
  287. X  #+ExCL          `()
  288. X  #+KCL           `()
  289. X  #+(and DEC VAX) `(caddr ,lc))
  290. X
  291. X(defmacro compiled-function-code (cf)  
  292. X  #+Xerox         `()
  293. X  #+Symbolics     cf
  294. X  #+ExCL          `()
  295. X  #+KCL           `()
  296. X  #+(and DEC VAX) `())
  297. X
  298. X(eval-when (load eval)
  299. X  (let ((dummies ()))
  300. X    (dotimes (i funcallable-instance-closure-size)
  301. X      (push (gentemp "Dummy Closure Variable ") dummies))
  302. X    (compile 'make-funcallable-instance-1    ;For the time being, this use
  303. X         `(lambda ()            ;of compile at load time is
  304. X        (let (new-fin ,@dummies)    ;simpler than using #.
  305. X          (setq new-fin #'(lambda ()
  306. X                    ,@(mapcar #'(lambda (d)
  307. X                          `(setq ,d (dummy-fn ,d)))
  308. X                          dummies)))
  309. X          (lexical-closure-env-set
  310. X            (lexical-closure-env new-fin)
  311. X            (1- funcallable-instance-closure-size)
  312. X            *funcallable-instance-marker*
  313. X            t)
  314. X          new-fin)))))
  315. X
  316. X(defmacro funcallable-instance-p (x)
  317. X  (once-only (x)
  318. X    `(and (lexical-closure-p ,x)
  319. X      (let ((env (lexical-closure-env ,x)))
  320. X        (and (eq (lexical-closure-env-ref
  321. X               env (1- funcallable-instance-closure-size) t)
  322. X             *funcallable-instance-marker*))))))
  323. X
  324. X(defun set-funcallable-instance-function-1 (fin new-value)
  325. X  (cond ((lexical-closure-p new-value)
  326. X     (let* ((fin-env (lexical-closure-env fin))
  327. X        (new-env (lexical-closure-env new-value))
  328. X        (new-env-size (lexical-closure-env-size new-env))
  329. X        (fin-env-size (- funcallable-instance-closure-size
  330. X                 (length funcallable-instance-data))))
  331. X       (cond ((<= new-env-size fin-env-size)
  332. X          (dotimes (i new-env-size)
  333. X            (lexical-closure-env-set
  334. X              fin-env i (lexical-closure-env-ref new-env i nil) nil))
  335. X          (setf (lexical-closure-code fin)
  336. X            (lexical-closure-code new-value)))
  337. X         (t            
  338. X          (set-funcallable-instance-function-1
  339. X            fin (make-trampoline new-value))))))
  340. X    (t
  341. X     #+Symbolics
  342. X     (set-funcallable-instance-function-1 fin
  343. X                          (make-trampoline new-value))
  344. X     #-Symbolics
  345. X     (setf (lexical-closure-code fin)
  346. X           (compiled-function-code new-value)))))
  347. X    
  348. X(defmacro funcallable-instance-data-1 (fin data)
  349. X  `(lexical-closure-env-ref
  350. X     (lexical-closure-env ,fin)
  351. X     (- funcallable-instance-closure-size
  352. X    (position ,data funcallable-instance-data)
  353. X    2)
  354. X     nil))
  355. X
  356. X(defsetf funcallable-instance-data-1 (fin data) (new-value)
  357. X  `(lexical-closure-env-set
  358. X     (lexical-closure-env ,fin)
  359. X     (- funcallable-instance-closure-size
  360. X    (position ,data funcallable-instance-data)
  361. X    2)
  362. X     ,new-value
  363. X     nil))
  364. X
  365. X);
  366. X
  367. X
  368. X(defun make-trampoline (function)
  369. X  #'(lambda (&rest args)
  370. X      (apply function args)))
  371. X
  372. X(defun set-funcallable-instance-function (fin new-value)
  373. X  (cond ((not (funcallable-instance-p fin))
  374. X     (error "~S is not a funcallable-instance"))
  375. X    ((not (functionp new-value))
  376. X     (error "~S is not a function."))
  377. X    ((compiled-function-p new-value)
  378. X     (set-funcallable-instance-function-1 fin new-value))
  379. X    (t
  380. X     (set-funcallable-instance-function-1 fin
  381. X                          (make-trampoline new-value)))))
  382. X
  383. X
  384. X(eval-when (eval load)
  385. X  (setq *class-of*
  386. X    '(lambda (x) 
  387. X       (or (and (%instancep x)
  388. X            (%instance-class-of x))
  389. X           (and (funcallable-instance-p x)
  390. X            (funcallable-instance-class x))
  391. X           (class-named (type-of x) t))))
  392. X
  393. X  (recompile-class-of))
  394. X
  395. X
  396. X(defmacro funcallable-instance-class (fin)
  397. X  `(funcallable-instance-data-1 ,fin 'class))
  398. X
  399. X(defmacro funcallable-instance-wrapper (fin)
  400. X  `(funcallable-instance-data-1 ,fin 'wrapper))
  401. X
  402. X(defmacro funcallable-instance-static-slots (fin)
  403. X  `(funcallable-instance-data-1 ,fin 'static-slots))
  404. X
  405. X(defmacro funcallable-instance-dynamic-slots (fin)
  406. X  `(funcallable-instance-data-1 ,fin 'dynamic-slots))
  407. X
  408. X(defun make-funcallable-instance (class wrapper number-of-static-slots)
  409. X  (let ((fin (make-funcallable-instance-1))
  410. X    (static-slots (make-memory-block number-of-static-slots))
  411. X    (dynamic-slots ()))
  412. X    (setf (funcallable-instance-class fin) class
  413. X      (funcallable-instance-wrapper fin) wrapper
  414. X      (funcallable-instance-static-slots fin) static-slots
  415. X      (funcallable-instance-dynamic-slots fin) dynamic-slots)
  416. X    fin))
  417. X
  418. X
  419. X;;; By macroleting the definitions of:
  420. X;;;   IWMC-CLASS-CLASS-WRAPPER
  421. X;;;   IWMC-CLASS-STATIC-SLOTS
  422. X;;;   IWMC-CLASS-DYNAMIC-SLOTS
  423. X;;;   get-slot-using-class--class-internal   ;These are kind of a
  424. X;;;   put-slot-using-class--class-internal   ;hack, solidfy this.
  425. X;;;
  426. X;;; we can use all the existing code for metaclass class.
  427. X;;; 
  428. X(defmacro with-funcallable-class-as-class ((instance checkp)
  429. X                       &body body)
  430. X  (once-only (instance)
  431. X    `(let ((.class. (funcallable-instance-p ,instance)))
  432. X       ,(and checkp
  433. X         `(or .class.
  434. X          (error "~S is not an instance with meta-class ~
  435. X                          funcallable-class." ,instance)))
  436. X       (macrolet ((iwmc-class-class-wrapper (instance)
  437. X            `(funcallable-instance-wrapper ,instance))
  438. X          (iwmc-class-static-slots (instance)
  439. X            `(funcallable-instance-static-slots ,instance))
  440. X          (iwmc-class-dynamic-slots (instance)
  441. X            `(funcallable-instance-dynamic-slots ,instance))
  442. X          (get-slot-using-class--class-internal
  443. X            (class object slot-name
  444. X               dont-call-slot-missing-p default)
  445. X            `(with-slot-internal--class (,class ,object
  446. X                         ,slot-name nil)
  447. X               (:instance (index)
  448. X            (get-static-slot--class ,object index))
  449. X               (:dynamic (loc newp) (if (eq newp t)
  450. X                        (setf (car loc) ,default)
  451. X                        (car loc)))
  452. X               (:class (slotd) (slotd-default slotd))
  453. X               (nil () (unless ,dont-call-slot-missing-p
  454. X                 (slot-missing ,object ,slot-name)))))
  455. X          (put-slot-using-class--class-internal
  456. X            (class object slot-name new-value
  457. X               dont-call-slot-missing-p)
  458. X            `(with-slot-internal--class (,class ,object
  459. X                         ,slot-name
  460. X                         ,dont-call-slot-missing-p)
  461. X               (:instance (index)
  462. X            (setf (get-static-slot--class ,object
  463. X                              index)
  464. X                  ,new-value))
  465. X               (:dynamic (loc) (setf (car loc) ,new-value))
  466. X               (:class (slotd) (setf (slotd-default slotd)
  467. X                         ,new-value))
  468. X               (nil () (unless ,dont-call-slot-missing-p
  469. X                 (slot-missing ,object ,slot-name))))))
  470. X     ,@body))))
  471. X
  472. X  ;;   
  473. X;;;;;; 
  474. X  ;;   
  475. X
  476. X
  477. X(defmacro get-slot--funcallable-class (fnc-instance slot-name)
  478. X  (once-only (fnc-instance slot-name)
  479. X    `(with-funcallable-class-as-class (,fnc-instance t)
  480. X       (get-slot--class ,fnc-instance ,slot-name))))
  481. X
  482. X(defmacro put-slot--funcallable-class (fnc-instance slot-name new-value)
  483. X  (once-only (fnc-instance slot-name)
  484. X    `(with-funcallable-class-as-class (,fnc-instance t)
  485. X       ;; Cheat a little bit here, its worth it.
  486. X       ,(if (constantp slot-name)
  487. X        (if (eq (eval slot-name) 'function)
  488. X        `(progn (set-funcallable-instance-function ,fnc-instance
  489. X                               ,new-value)
  490. X            (put-slot--class ,fnc-instance ,slot-name ,new-value))
  491. X        `(put-slot--class ,fnc-instance ,slot-name ,new-value))
  492. X        `(if (eq ,slot-name 'function)
  493. X         (progn (set-funcallable-instance-function ,fnc-instance
  494. X                               ,new-value)
  495. X            (put-slot--class ,fnc-instance ,slot-name ,new-value))
  496. X         (put-slot--class ,fnc-instance ,slot-name ,new-value))))))
  497. X
  498. X  ;;   
  499. X;;;;;; 
  500. X  ;;   
  501. X
  502. X(defclass funcallable-class (class)
  503. X  ())
  504. X
  505. X(defmeth check-super-metaclass-compatibility ((fnc-class funcallable-class)
  506. X                          (class class))
  507. X  (ignore fnc-class)
  508. X  (null (class-slots class)))
  509. X
  510. X
  511. X(defmeth get-slot-using-class ((ignore funcallable-class)
  512. X                   instance
  513. X                   slot-name)
  514. X  (get-slot--funcallable-class instance slot-name))
  515. X
  516. X(defmeth put-slot-using-class ((ignore funcallable-class)
  517. X                   instance
  518. X                   slot-name
  519. X                   new-value)
  520. X  (put-slot--funcallable-class instance slot-name new-value))
  521. X
  522. X(defmeth make-instance ((class funcallable-class))
  523. X  (let ((class-wrapper (class-wrapper class)))
  524. X    (if class-wrapper                ;Are there any instances?
  525. X        ;; If there are instances, the class is OK, just go ahead and
  526. X        ;; make the instance.
  527. X    (make-funcallable-instance class
  528. X                   class-wrapper
  529. X                   (class-no-of-instance-slots class))
  530. X        ;; Do first make-instance-time error-checking, build the class
  531. X        ;; wrapper and call ourselves again to really build the instance.
  532. X        (progn
  533. X          ;; no first time error checking yet.
  534. X          (setf (class-wrapper class) (make-class-wrapper class))
  535. X          (make-instance class)))))
  536. X
  537. X(eval-when (compile load eval)
  538. X
  539. X(define-function-template iwmc-funcallable-class-accessor () '(slot-name)
  540. X  `(function (lambda (iwmc-class)
  541. X           (get-slot--funcallable-class iwmc-class slot-name))))
  542. X
  543. X(define-function-template iwmc-funcallable-class-accessor-setf (read-only-p)
  544. X                                   '(slot-name)
  545. X  (if read-only-p
  546. X      `(function
  547. X         (lambda (iwmc-class new-value)
  548. X       (error "~S is a read only slot." slot-name)))
  549. X      `(function
  550. X         (lambda (iwmc-class new-value)
  551. X       (put-slot--funcallable-class iwmc-class slot-name new-value)))))
  552. X)
  553. X
  554. X(eval-when (load)
  555. X  (pre-make-templated-function-constructor iwmc-class-accessor)
  556. X  (pre-make-templated-function-constructor iwmc-class-accessor-setf nil)
  557. X  (pre-make-templated-function-constructor iwmc-class-accessor-setf t))
  558. X
  559. X(defmethod make-iwmc-class-accessor ((ignore funcallable-class) slotd)
  560. X  (funcall
  561. X    (get-templated-function-constructor 'iwmc-funcallable-class-accessor)
  562. X    (slotd-name slotd)))
  563. X
  564. X(defmethod make-iwmc-class-accessor-setf ((ignore funcallable-class) slotd)
  565. X  (funcall
  566. X    (get-templated-function-constructor 'iwmc-funcallable-class-accessor-setf
  567. X                    (slotd-read-only slotd))
  568. X    (slotd-name slotd)))
  569. X
  570. X
  571. X  ;;   
  572. X;;;;;; 
  573. X  ;;   
  574. X
  575. X#|
  576. X
  577. X(defclass generic-function (discriminator)
  578. X  ((function #'(lambda (&rest ignore) ignore (error "foo")))
  579. X   (name ())     
  580. X   (methods ())
  581. X   (discriminating-function ())
  582. X   (cache ())
  583. X   (dispatch-order ())
  584. X   (method-combination-type ())
  585. X   (method-combination-parameters ())
  586. X   (methods-combine-p ()))
  587. X  (:metaclass funcallable-class))
  588. X
  589. X(defmeth install-discriminating-function ((gfun generic-function)
  590. X                      where
  591. X                      function
  592. X                      &optional inhibit-compile-p)
  593. X  (check-type where symbol "a symbol other than NIL")
  594. X  (check-type function function "a funcallable object")
  595. X  
  596. X  (when (and (listp function)
  597. X         (eq (car function) 'lambda)
  598. X         (null inhibit-compile-p))
  599. X    (setq function (compile nil function)))
  600. X
  601. X  (setf (get-slot gfun 'function) function))
  602. X
  603. X(defun convert-to-generic-functions ()
  604. X  (let ((discriminators ()))
  605. X    (do-symbols (s (find-package 'pcl))
  606. X      (when (discriminator-named s) (push s discriminators)))
  607. X
  608. X
  609. X    ))
  610. X
  611. X(defun convert-generic-function (name)
  612. X  (let ((discriminator (discriminator-named name))
  613. X    (gfun (make 'generic-function)))
  614. X    (setf (funcallable-instance-static-slots gfun)
  615. X      (iwmc-class-static-slots discriminator))
  616. X    (setf (funcallable-instance-dynamic-slots gfun)
  617. X      (iwmc-class-dynamic-slots discriminator))
  618. X    (install-discriminating-function gfun
  619. X                     ()
  620. X                     (symbol-function name))
  621. X    (set name gfun)))
  622. X
  623. X
  624. X(defclass bar ()
  625. X  ((function nil)
  626. X   (a 1)
  627. X   (b 2))
  628. X  (:metaclass funcallable-class))
  629. X
  630. X(defclass foo ()
  631. X  ((a nil)
  632. X   (b nil)
  633. X   (c nil))
  634. X  (:metaclass funcallable-class))
  635. X
  636. X|#
  637. X
  638. END_OF_FILE
  639. if test 20567 -ne `wc -c <'gfun-low.l'`; then
  640.     echo shar: \"'gfun-low.l'\" unpacked with wrong size!
  641. fi
  642. # end of 'gfun-low.l'
  643. fi
  644. if test -f 'test.l' -a "${1}" != "-c" ; then 
  645.   echo shar: Will not clobber existing file \"'test.l'\"
  646. else
  647. echo shar: Extracting \"'test.l'\" \(21892 characters\)
  648. sed "s/^X//" >'test.l' <<'END_OF_FILE'
  649. X;;;-*- Mode:LISP; Package: PCL; Base:10; Syntax:Common-lisp -*-
  650. X;;;
  651. X;;; *************************************************************************
  652. X;;; Copyright (c) 1985 Xerox Corporation.  All rights reserved.
  653. X;;;
  654. X;;; Use and copying of this software and preparation of derivative works
  655. X;;; based upon this software are permitted.  Any distribution of this
  656. X;;; software or derivative works must comply with all applicable United
  657. X;;; States export control laws.
  658. X;;; 
  659. X;;; This software is made available AS IS, and Xerox Corporation makes no
  660. X;;; warranty about the software, its performance or its conformity to any
  661. X;;; specification.
  662. X;;; 
  663. X;;; Any person obtaining a copy of this software is requested to send their
  664. X;;; name and post office or electronic mail address to:
  665. X;;;   CommonLoops Coordinator
  666. X;;;   Xerox Artifical Intelligence Systems
  667. X;;;   2400 Hanover St.
  668. X;;;   Palo Alto, CA 94303
  669. X;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
  670. X;;;
  671. X;;; Suggestions, comments and requests for improvements are also welcome.
  672. X;;; *************************************************************************
  673. X;;; 
  674. X;;; Testing code.
  675. X;;;
  676. X
  677. X(in-package 'pcl)
  678. X
  679. X;;; Because CommonLoops runs in itself so much, the notion of a test file for
  680. X;;; it is kind of weird.
  681. X;;;
  682. X;;; If all of PCL loads then many of the tests in this file (particularly
  683. X;;; those at the beginning) are sure to work.  Those tests exists primarily
  684. X;;; to help debug things when low-level changes are made to PCL, or when a
  685. X;;; particular port customizes low-level code.
  686. X;;;
  687. X;;; Some of the other tests are "real" in the sense that they test things
  688. X;;; that PCL itself does not use, so might be broken.
  689. X;;; 
  690. X;;; NOTE:
  691. X;;;   The tests in this file do not appear in random order!  They
  692. X;;;   depend on state  which has already been set up in order to run.
  693. X;;;
  694. X;;;   As a convention foo, bar and baz are used for classes and
  695. X;;;   discriminators which are just for the current test.  By
  696. X;;;   default, do-test resets those names before running the current
  697. X;;;   test.  Other names like x, y, z, method-1... are used to name
  698. X;;;   classes and discriminators which last the life of the file.
  699. X;;; 
  700. X
  701. X(defvar *without-errors*
  702. X    (or #+Symbolics #'(lambda (form)
  703. X                `(multiple-value-bind (.values. .errorp.)
  704. X                 (si::errset ,form nil)
  705. X                   (declare (ignore .values.))
  706. X                   .errorp.))
  707. X        #+Xerox     #'(lambda (form)
  708. X                `(xcl:condition-case (progn ,form nil)
  709. X                   (error () t)))
  710. X        
  711. X        nil))
  712. X
  713. X(defmacro without-errors (&body body)
  714. X  (if *without-errors*
  715. X      (funcall *without-errors* `(progn ,@body))
  716. X      (error "Calling WITHOUT-ERRORS when *without-errors* is nil.")))
  717. X
  718. X#-HP (defmacro do-test (name&options &body body)
  719. X  (let ((name (if (listp name&options) (car name&options) name&options))
  720. X    (options (if (listp name&options) (cdr name&options) ())))
  721. X    (keyword-bind ((clear t)
  722. X           (should-error nil))
  723. X          options
  724. X      (cond ((and should-error (null *without-errors*))
  725. X         `(format t
  726. X        "~&Skipping testing ~A,~%~
  727. X             because can't ignore errors in this Common Lisp."
  728. X        ',name))
  729. X        (t
  730. X         `(progn
  731. X        (format t "~&Testing ")
  732. X        (format t ,name)
  733. X        (format t "... ")
  734. X        ,(when clear
  735. X           '(progn (dolist (x '(foo bar baz))
  736. X                 (setf (discriminator-named x) nil)
  737. X                 (fmakunbound x)
  738. X                 (setf (class-named x) nil))))
  739. X        (if ,(if should-error
  740. X             `(without-errors (progn ,@body))
  741. X             `(progn ,@body))
  742. X            (format t "OK")
  743. X            (progn (format t "FAILED")
  744. X               (error "Test Failed: ~A" ',name)))))))))
  745. X
  746. X#+HP (defmacro do-test (name&options &body body)
  747. X  (let ((name (if (listp name&options) (car name&options) name&options))
  748. X    (options (if (listp name&options) (cdr name&options) ())))
  749. X    (keyword-bind ((clear t)
  750. X           (should-error nil))
  751. X          options
  752. X      (cond ((and should-error (null *without-errors*))
  753. X         `(format t
  754. X        "~&Skipping testing ~A,~%~
  755. X             because can't ignore errors in this Common Lisp."
  756. X        ',name))
  757. X        (t
  758. X         `(progn
  759. X        (format t "~&Testing ~A..." ,name)
  760. X        ,(when clear
  761. X           '(progn (dolist (x '(foo bar baz))
  762. X                 (setf (discriminator-named x) nil)
  763. X                 (fmakunbound x)
  764. X                 (setf (class-named x) nil))))
  765. X        
  766. X         ,@(butlast body)
  767. X         (if ,(if should-error
  768. X             `(without-errors (progn ,@body))
  769. X             `(progn ,@(last body)))
  770. X            (format t "OK")
  771. X            (progn (format t "FAILED")
  772. X               (error "Test Failed: ~A" ',name)))))))))
  773. X
  774. X(defun permutations (elements length)
  775. X  (if (= length 1)
  776. X      (iterate ((x in elements)) (collect (list x)))
  777. X      (let ((sub-permutations (permutations elements (- length 1))))
  778. X        (iterate ((x in elements))
  779. X          (join (iterate ((y in sub-permutations))
  780. X                  (collect (cons x y))))))))
  781. X
  782. X  ;;   
  783. X;;;;;; 
  784. X  ;;   
  785. X
  786. X
  787. X(eval-when (load eval)
  788. X  (format t "~&~%~%Testing Extremely low-level stuff..."))
  789. X
  790. X(do-test ("Memory Block Primitives" :clear nil)
  791. X  (let ((block (make-memory-block 10))
  792. X        (tests (iterate ((i from 0 below 10)) (collect (make-list 1)))))
  793. X    (and (numberp (memory-block-size block))
  794. X         (= (memory-block-size block) 10)
  795. X         (progn (iterate ((i from 0) (test in tests))
  796. X                  (setf (memory-block-ref block i) test))
  797. X                (iterate ((i from 0) (test in tests))
  798. X                  (unless (eq (memory-block-ref block i) test) (return nil))
  799. X                  (finally (return t)))))))
  800. X
  801. X(do-test ("Class Wrapper Caching" :clear nil)
  802. X  (let* ((wrapper (make-class-wrapper 'test))
  803. X         (offset (class-wrapper-get-slot-offset wrapper 'foo))
  804. X         (value (list ())))
  805. X    
  806. X    (and (eq 'foo  (setf (class-wrapper-cached-key wrapper offset) 'foo))
  807. X         (eq value (setf (class-wrapper-cached-val wrapper offset) value))
  808. X         (eq 'foo  (class-wrapper-cached-key wrapper offset))
  809. X         (eq value (class-wrapper-cached-val wrapper offset)))))
  810. X
  811. X(do-test ("Flushing Class-Wrapper caches" :clear nil)
  812. X  (let* ((wrapper (make-class-wrapper 'test))
  813. X         (offset (class-wrapper-get-slot-offset wrapper 'foo)))
  814. X    (setf (class-wrapper-cached-key wrapper offset) 'foo)
  815. X    (flush-class-wrapper-cache wrapper)
  816. X    (neq 'foo  (class-wrapper-cached-key wrapper offset))))
  817. X
  818. X(do-test "Class Wrapper Caching"
  819. X  (let ((slots '(;; Some random important slots.
  820. X         name class-wrapper class-precedence-list
  821. X         direct-supers direct-subclasses direct-methods
  822. X         no-of-instance-slots instance-slots
  823. X         local-supers
  824. X         non-instance-slots local-slots  prototype))
  825. X    (wrapper (make-class-wrapper 'test))
  826. X    (hits 0))
  827. X    (iterate ((slot in slots))
  828. X      (let ((offset (class-wrapper-get-slot-offset wrapper slot)))
  829. X    (setf (class-wrapper-cached-key wrapper offset) slot)))
  830. X    (iterate ((slot in slots))
  831. X      (let ((offset (class-wrapper-get-slot-offset wrapper slot)))
  832. X    (and (eq (class-wrapper-cached-key wrapper offset) slot)
  833. X         (incf hits))))
  834. X    (format t
  835. X        " (~D% hit) "
  836. X        (* 100.0 (/ hits (float (length slots)))))
  837. X    t))
  838. X
  839. X;(do-test "static slot-storage"
  840. X;  (let ((static-slots (%allocate-static-slot-storage--class 5)))
  841. X;    (iterate ((i from 0))
  842. X;      (when (= i 5) (return t))
  843. X;      (let ((cons (list ()))
  844. X;            (index (%convert-slotd-position-to-slot-index i)))
  845. X;        (setf (%static-slot-storage-get-slot--class static-slots index) cons)
  846. X;        (or (eq cons
  847. X;        (%static-slot-storage-get-slot--class static-slots index))
  848. X;            (return nil))))))
  849. X
  850. X
  851. X(eval-when (load eval) (format t "~&~%~%Testing High-Level stuff..."))
  852. X
  853. X
  854. X
  855. X(defvar *built-in-classes*
  856. X        '((T              T)
  857. X          (NUMBER         1)
  858. X          (RATIO       1/2                          1/2)
  859. X          (COMPLEX)
  860. X          (INTEGER        1)
  861. X          (RATIO)
  862. X          (FIXNUM         most-positive-fixnum         most-positive-fixnum)
  863. X          (BIGNUM         (+ most-positive-fixnum 1)   (+ most-positive-fixnum 1)) 
  864. X          SHORT-FLOAT SINGLE-FLOAT DOUBLE-FLOAT LONG-FLOAT
  865. X          (FLOAT          1.1)
  866. X          (NULL           ()                           ())
  867. X          (STANDARD-CHAR  #\a)
  868. X          (STRING-CHAR    #\a)
  869. X          (CHARACTER      #\a                          #\a)
  870. X          BIT-VECTOR
  871. X          (STRING         (make-string 1)              (make-string 1))
  872. X          (ARRAY          (make-array 1))
  873. X          SIMPLE-ARRAY SIMPLE-VECTOR SIMPLE-STRING SIMPLE-BIT-VECTOR
  874. X          (VECTOR         (make-string 1))
  875. X          (VECTOR         (make-array 1))
  876. X          (LIST           '(1 2 3))
  877. X          (SEQUENCE       (make-string 1))
  878. X          (SEQUENCE       (make-array 1))
  879. X          (SEQUENCE       (make-list 1))                             
  880. X          (HASH-TABLE     (make-hash-table :size 1)    (make-hash-table :size 1))
  881. X          (READTABLE      *readtable*                  *readtable*)
  882. X          (PACKAGE        *package*                    *package*)
  883. X          (PATHNAME       (make-pathname :name "foo")  (make-pathname :name "foo"))
  884. X          (STREAM         *terminal-io*                *terminal-io*)
  885. X          (RANDOM-STATE   (make-random-state)          (make-random-state))
  886. X          (CONS           (cons 1 2)                   (cons 1 2))
  887. X          (SYMBOL         'foo                         'foo)
  888. X          COMMON))
  889. X
  890. X(do-test "existence of built-in classes"
  891. X  (not (dolist (entry *built-in-classes*)
  892. X         (let ((type (if (listp entry) (car entry) entry)))
  893. X           (or (class-named type t)
  894. X               (progn (format t "Missing the built-in class named: ~S" type)
  895. X                      (return t)))))))  
  896. X
  897. X;;; See how CLASS-OF works.
  898. X;(eval-when (load eval)
  899. X;  (format t "~%Check to see how well portable CLASS-OF works... ")
  900. X;  (let ((lost ()))
  901. X;    (dolist (entry *built-in-classes*)
  902. X;      (or (not (listp entry))
  903. X;      (null (cddr entry))
  904. X;      (let* ((thing (eval (caddr entry)))
  905. X;         (class (class-of thing)))
  906. X;        (and class (eq (class-name class) (car entry))))
  907. X;      (progn (setq lost t)
  908. X;         (format t
  909. X;             "~&WARNING: Can't define methods on: ~S."
  910. X;             (car entry)))))
  911. X;    (when lost (terpri) (terpri))
  912. X;    (format t "OK")))
  913. X
  914. X(do-test "existence of discriminators for accessors of early classes"
  915. X  ;; Because accessors are done with add-method, and this has to be done
  916. X  ;; specially for early classes it is worth testing to make sure that
  917. X  ;; the discriminators got created for the accessor of early classes.
  918. X  (not
  919. X    (dolist (class '(t object essential-class class discriminator method))
  920. X      (setq class (class-named class))
  921. X      (or (not (dolist (slotd (class-instance-slots class))
  922. X                 (and (slotd-accessor slotd)
  923. X                      (or (discriminator-named (slotd-accessor slotd))
  924. X                          (return nil)))))
  925. X          (not (dolist (slotd (class-non-instance-slots class))
  926. X                 (and (slotd-accessor slotd)
  927. X                      (or (discriminator-named (slotd-accessor slotd))
  928. X                          (return nil)))))))))
  929. X
  930. X(do-test "a simple defstruct"
  931. X  (ndefstruct (x (:class class))
  932. X    (a 1)
  933. X    (b 2))
  934. X
  935. X  (and (fboundp 'make-x)
  936. X       (fboundp 'x-p)
  937. X       (fboundp 'copy-x)
  938. X       (fboundp 'x-a)
  939. X       (fboundp 'x-b)
  940. X       (typep--class (make-x) 'x)
  941. X       (x-p (make-x))
  942. X       (equal (x-a (make-x)) 1)
  943. X       (equal (x-a (make-x :a 3)) 3)
  944. X       (x-p (copy-x (make-x)))
  945. X       ))
  946. X
  947. X(do-test "obsolete-class stuff"
  948. X  (and (class-named 'obsolete-class)
  949. X       (let ((old-x-class (class-named 'x))
  950. X             (old-x-instance (make-x)))
  951. X         
  952. X         (ndefstruct (x (:class class))
  953. X                     (a 3))
  954. X         (and (neq (class-of old-x-instance) (class-named 'x))
  955. X              (= (x-a old-x-instance) 1)))))
  956. X
  957. X(do-test "multiple constructors"
  958. X  (ndefstruct (x (:class class)
  959. X                 (:constructor make-x)
  960. X                 (:constructor make-x-1 (a b)))
  961. X    a
  962. X    b)
  963. X  (and (fboundp 'make-x)
  964. X       (fboundp 'make-x-1)
  965. X       (equal (get-slot (make-x :a 1 :b 2) 'a) 1)
  966. X       (equal (get-slot (make-x :a 1 :b 2) 'b) 2)
  967. X       (equal (get-slot (make-x-1 2 1) 'a) 2)
  968. X       (equal (get-slot (make-x-1 2 1) 'b) 1)))
  969. X
  970. X(do-test "the :print-function defstruct-option"
  971. X
  972. X  (ndefstruct (x (:class class)
  973. X                 (:print-function x-print-function))
  974. X    a
  975. X    b)
  976. X
  977. X  (defun x-print-function (object stream level)
  978. X    (when (and (x-p object)
  979. X               (streamp stream)                 ;Don't be breaking my test file
  980. X               (numberp level))                 ;because of your problems.
  981. X      (throw 'x 'x)))
  982. X
  983. X  (eq (catch 'x (prin1 (make 'x))) 'x))
  984. X
  985. X;;; ** need more tests in here,
  986. X;;; test the basic iwmc-class structure
  987. X;;; test class-wrappers some more
  988. X;;; 
  989. X
  990. X;;; OK, now we know that simple defstruct works and that obsolete classes work.
  991. X;;; Now we set up some real simple classes that we can use for the rest of the
  992. X;;; file.
  993. X;;;
  994. X(ndefstruct (i (:class class)))                     ;(i ..)
  995. X(ndefstruct (j (:class class)))                     ;(j ..)
  996. X(ndefstruct (k (:class class)))                     ;(k ..)
  997. X
  998. X(ndefstruct (l (:class class) (:include (i))))      ;(l i ..)
  999. X(ndefstruct (m (:class class) (:include (i j))))    ;(m i j ..)
  1000. X(ndefstruct (n (:class class) (:include (k))))      ;(n k ..)
  1001. X
  1002. X(ndefstruct (q (:class class) (:include (i))))      ;(q i ..)
  1003. X(ndefstruct (r (:class class) (:include (m))))      ;(r m i j ..)
  1004. X(ndefstruct (s (:class class) (:include (n i k))))  ;(s n i k ..)
  1005. X
  1006. X(do-test "classical methods"
  1007. X  
  1008. X  (defmeth foo ((x i)) x 'i)  
  1009. X  (defmeth foo ((x n)) x 'n)
  1010. X  (defmeth foo ((x s)) x 's)
  1011. X
  1012. X  (and (eq (foo (make-i)) 'i)
  1013. X       (eq (foo (make-n)) 'n)
  1014. X       (eq (foo (make-s)) 's)))
  1015. X
  1016. X(do-test "run-super"
  1017. X
  1018. X  (defmeth foo (o) o ())
  1019. X  
  1020. X  (defmeth foo ((o i)) o (cons 'i (run-super)))
  1021. X  (defmeth foo ((o m)) o (cons 'm (run-super)))
  1022. X  (defmeth foo ((o n)) o (cons 'n (run-super)))
  1023. X  (defmeth foo ((o q)) o (cons 'q (run-super)))
  1024. X  (defmeth foo ((o r)) o (cons 'r (run-super)))
  1025. X  (defmeth foo ((o s)) o (cons 's (run-super)))
  1026. X
  1027. X  (let ((i (make-i)) (m (make-m)) (q (make-q)) (r (make-r)) (s (make-s)))
  1028. X    (and (equal (foo i) '(i))
  1029. X         (equal (foo m) '(m i))
  1030. X         (equal (foo q) '(q i))
  1031. X         (equal (foo r) '(r m i))
  1032. X         (equal (foo s) '(s n i)))))
  1033. X
  1034. X(do-test "multi-methods when first 3 args are discriminated on"
  1035. X  (let ((permutations (permutations '(i n r) 3)))
  1036. X    (mapcar #'(lambda (p)
  1037. X                (EVAL `(defmeth foo ,(mapcar 'list '(x y z) p) x y z ',p)))
  1038. X            permutations)
  1039. X    (every #'(lambda (p)
  1040. X               (equal (apply 'foo (mapcar 'make p)) p))
  1041. X           permutations)))
  1042. X
  1043. X(do-test "multi-methods when assorted args are discriminated on"
  1044. X  (let ((permutations (permutations '(i n r nil) 3)))
  1045. X    (mapc #'(lambda (p)
  1046. X          (EVAL `(defmeth foo
  1047. X                  ,(mapcar #'(lambda (arg type-spec)
  1048. X                       (if type-spec
  1049. X                           (list arg type-spec) arg))
  1050. X                       '(arg1 arg2 arg3)
  1051. X                       p)
  1052. X               arg1 arg2 arg3 ',p)))
  1053. X      permutations)
  1054. X    (every #'(lambda (p)
  1055. X               (equal (apply 'foo
  1056. X                 (mapcar #'(lambda (x) (and x (make x))) p)) p))
  1057. X           permutations)))
  1058. X
  1059. X
  1060. X
  1061. X;(do-test "anonymous discriminators"
  1062. X;  
  1063. X;  (let ((foo (make 'discriminator))
  1064. X;        (proto-method (class-prototype (class-named 'method))))
  1065. X;    (add-method-internal  foo proto-method '(thing) (list (class-named 'x)) '(lambda (thing) thing 'x))
  1066. X;    (add-method foo '(thing) (list (class-named 'y)) '(lambda (thing) thing 'y))
  1067. X;    (add-method foo '(thing) (list (class-named 'z)) '(lambda (thing) thing 'z))
  1068. X;
  1069. X;    (let ((function (discriminator-discriminating-function foo)))
  1070. X;      (and (eq (funcall function (make 'x)) 'x)
  1071. X;          (eq (funcall function (make 'y)) 'y)
  1072. X;          (eq (funcall function (make 'z)) 'z)))))
  1073. X
  1074. X
  1075. X
  1076. X(do-test "Simple with test -- does not really exercise the walker."
  1077. X  
  1078. X  (ndefstruct (foo (:class class))
  1079. X    (x 0)
  1080. X    (y 0))
  1081. X
  1082. X  (defmeth foo ((obj foo))
  1083. X    (with (obj)
  1084. X      (list x y)))
  1085. X
  1086. X  (defmeth bar ((obj foo))
  1087. X    (with ((obj obj-))
  1088. X      (setq obj-x 1
  1089. X            obj-y 2)))
  1090. X
  1091. X  (and (equal '(0 0) (foo (make-foo)))
  1092. X       (equal '(1 2) (foo (make-foo :x 1 :y 2)))
  1093. X       (let ((foo (make-foo)))
  1094. X         (bar foo)
  1095. X         (and (equal (get-slot foo 'x) 1)
  1096. X              (equal (get-slot foo 'y) 2)))))
  1097. X
  1098. X(do-test "Simple with* test -- does not really exercise the walker."
  1099. X  
  1100. X  (ndefstruct (foo (:class class))
  1101. X    (x 0)
  1102. X    (y 0))
  1103. X
  1104. X  (defmeth foo ((obj foo))
  1105. X    (with* (obj)
  1106. X      (list x y)))
  1107. X
  1108. X  (defmeth bar ((obj foo))
  1109. X    (with* ((obj obj-))
  1110. X      (setq obj-x 1
  1111. X            obj-y 2)))
  1112. X
  1113. X  (and (equal '(0 0) (foo (make-foo)))
  1114. X       (equal '(1 2) (foo (make-foo :x 1 :y 2)))
  1115. X       (let ((foo (make-foo)))
  1116. X         (bar foo)
  1117. X         (and (equal (get-slot foo 'x) 1)
  1118. X              (equal (get-slot foo 'y) 2)))))
  1119. X
  1120. X'(
  1121. X
  1122. X;;; setup for :daemon combination test
  1123. X;;;
  1124. X
  1125. X(do-test "setting up for :daemon method combination test"
  1126. X  
  1127. X  (ndefstruct (foo (:class class)))
  1128. X  (ndefstruct (bar (:class class) (:include (foo))))
  1129. X  (ndefstruct (baz (:class class) (:include (bar)))))
  1130. X
  1131. X(defvar *foo*)
  1132. X
  1133. X(defmeth foo ((x foo)) (push 'foo *foo*) 'foo)
  1134. X(defmeth (foo :before) ((x foo)) (push '(:before foo) *foo*))
  1135. X(defmeth (foo :after)  ((x foo)) (push '(:after foo) *foo*))
  1136. X
  1137. X(do-test (":before primary and :after all on same class." :clear nil)
  1138. X
  1139. X  (let ((*foo* ()))
  1140. X    (and (eq (foo (make 'foo)) 'foo)
  1141. X     (equal *foo* '((:after foo) foo (:before foo))))))
  1142. X
  1143. X(defmeth foo ((x bar)) (push 'bar *foo*) 'bar)
  1144. X
  1145. X(do-test (":before and :after inherited, primary from this class" :clear nil)
  1146. X
  1147. X  (let ((*foo* ()))
  1148. X    (and (eq (foo (make 'bar)) 'bar)
  1149. X     (equal *foo* '((:after foo) bar (:before foo))))))
  1150. X
  1151. X(do-test ("make sure shadowing primary in sub-class has no effect here"
  1152. X      :clear nil)
  1153. X  (let ((*foo* ()))
  1154. X    (and (eq (foo (make 'foo)) 'foo)
  1155. X     (equal *foo* '((:after foo) foo (:before foo))))))
  1156. X
  1157. X(defmeth (foo :before) ((x bar)) (push '(:before bar) *foo*))
  1158. X(defmeth (foo :after) ((x bar))  (push '(:after bar) *foo*))
  1159. X
  1160. X(do-test (":before both here and inherited~%~
  1161. X           :after both here and inherited~%~
  1162. X           primary from here"
  1163. X      :clear nil)
  1164. X  (let ((*foo* ()))
  1165. X    (and (eq (foo (make 'bar)) 'bar)
  1166. X     (equal (reverse *foo*)
  1167. X        '((:before bar) (:before foo) bar (:after foo) (:after bar))))))
  1168. X
  1169. X(defmeth foo ((x baz)) (push 'baz *foo*) 'baz)
  1170. X
  1171. X(do-test ("2 :before and 2 :after inherited, primary from here" :clear nil)
  1172. X  (let ((*foo* ()))
  1173. X    (and (eq (foo (make 'baz)) 'baz)
  1174. X     (equal (reverse *foo*)
  1175. X        '((:before bar) (:before foo) baz (:after foo) (:after bar))))))
  1176. X
  1177. X
  1178. X(do-test "setting up for :list method combination test"
  1179. X  (make-specializable 'foo :arglist '(x) :method-combination-type :list)
  1180. X  
  1181. X  (ndefstruct (foo (:class class)))
  1182. X  (ndefstruct (bar (:class class) (:include (foo))))
  1183. X  (ndefstruct (baz (:class class) (:include (bar)))))
  1184. X
  1185. X(defmeth foo ((x foo)) 'foo)
  1186. X
  1187. X(do-test ("single method, :list combined, from here" :clear nil)
  1188. X  (equal (foo (make 'foo)) '(foo)))
  1189. X
  1190. X(defmeth foo ((x bar)) 'bar)
  1191. X(do-test ("method from here and one inherited, :list combined" :clear nil)
  1192. X  (equal (foo (make 'bar)) '(foo bar)))
  1193. X
  1194. X(defmeth foo ((x baz)) 'baz)
  1195. X
  1196. X(do-test ("method from here, two inherited, :list combined" :clear nil)
  1197. X  (equal (foo (make 'baz)) '(foo bar baz)))
  1198. X
  1199. X(do-test ("make sure that more specific methods aren't in my combined method"
  1200. X      :clear nil)
  1201. X  (and (equal (foo (make 'foo)) '(foo))
  1202. X       (equal (foo (make 'bar)) '(foo bar))
  1203. X       (equal (foo (make 'baz)) '(foo bar baz))))
  1204. X
  1205. X)
  1206. X
  1207. X  ;;   
  1208. X;;;;;; things that bug fixes prompted.
  1209. X  ;;   
  1210. X
  1211. X
  1212. X(do-test "with inside of lexical closures"
  1213. X  ;; 6/20/86
  1214. X  ;; The walker was confused about what (FUNCTION (LAMBDA ..)) meant.  It
  1215. X  ;; didn't walk inside there.  Its sort of surprising this didn't get
  1216. X  ;; caught sooner.
  1217. X
  1218. X  (ndefstruct (foo (:class class))
  1219. X    (x 0)
  1220. X    (y 0))
  1221. X
  1222. X  (defun foo (fn foos)
  1223. X    (and foos (cons (funcall fn (car foos)) (foo fn (cdr foos)))))
  1224. X
  1225. X  (defun bar ()
  1226. X    (let ((the-foo (make 'foo :x 0 :y 3)))
  1227. X      (with ((the-foo () foo))
  1228. X    (foo #'(lambda (foo) (incf x) (decf y))
  1229. X         (make-list 3)))))
  1230. X
  1231. X  (equal (bar) '(2 1 0)))
  1232. X
  1233. X(do-test "redefinition of default method has proper effect"
  1234. X  ;; 5/26/86
  1235. X  ;; This was caused because the hair for trying to avoid making a
  1236. X  ;; new discriminating function didn't know that changing the default
  1237. X  ;; method was a reason to make a new discriminating function.  Fixed
  1238. X  ;; by always making a new discriminating function when a method is
  1239. X  ;; added or removed.  The template stuff should keep this from being
  1240. X  ;; expensive.
  1241. X
  1242. X  (defmeth foo ((x class)) 'class)
  1243. X  (defmeth foo (x) 'default)
  1244. X  (defmeth foo (x) 'new-default)
  1245. X
  1246. X  (eq (foo nil) 'new-default))
  1247. X
  1248. X
  1249. X(do-test ("extra keywords in init-plist cause an error" :should-error t)
  1250. X  ;; 5/26/86
  1251. X  ;; Remember that Common-Lisp defstruct signals errors if there are
  1252. X  ;; extra keywords in the &rest argument to make-foo.
  1253. X  
  1254. X  (ndefstruct (foo (:class class)) a b c)
  1255. X
  1256. X  (make 'foo :d 3))
  1257. X
  1258. X(do-test "run-super with T specifier for first arg"
  1259. X  ;; 5/29/86
  1260. X  ;; This was caused because run-super-internal didn't know about the
  1261. X  ;; type-specifier T being special.  This is yet another reason to
  1262. X  ;; flush that nonsense about keeping T special.
  1263. X
  1264. X  (defmeth foo (x y) '((t t)))
  1265. X
  1266. X  (defmeth foo (x (y k)) '((t k)))
  1267. X
  1268. X  (defmeth foo (x (y n)) (cons '(t n) (run-super)))
  1269. X
  1270. X  (defmeth foo ((x i) (y k)) '((i k)))
  1271. X
  1272. X  (defmeth foo ((x l) (y n)) (cons '(l n) (run-super)))
  1273. X
  1274. X
  1275. X  (and (equal (foo (make 'l) (make 'n)) '((l n) (i k)))
  1276. X       (equal (foo (make 'i) (make 'k)) '((i k)))
  1277. X       (equal (foo () (make 'k)) '((t k)))
  1278. X       (equal (foo () (make 'n)) '((t n) (t k)))))
  1279. X
  1280. X(do-test "with inside of with scopes correctly"
  1281. X  ;; 7/07/86
  1282. X
  1283. X  (ndefstruct (foo (:class class)
  1284. X           (:conc-name nil))
  1285. X    (foo 1))
  1286. X
  1287. X  (ndefstruct (bar (:class class)
  1288. X           (:conc-name nil))
  1289. X    (foo 1))
  1290. X
  1291. X
  1292. X  (defmeth foo ((bar bar)) bar ())
  1293. X
  1294. X  (defun bar (x)
  1295. X    (with* ((x "" foo))
  1296. X      (list foo (with ((x "" bar)) foo))))
  1297. X
  1298. X  (defun baz (x)
  1299. X    (with ((x "" bar))
  1300. X      (list foo (with* ((x "" foo)) foo))))
  1301. X
  1302. X  (and (equal (bar (make 'bar)) '(1 nil))
  1303. X       (equal (baz (make 'bar)) '(nil 1))
  1304. X
  1305. X       (equal (bar (make 'foo)) '(1 1))
  1306. X       (equal (baz (make 'foo)) '(1 1))))
  1307. X
  1308. END_OF_FILE
  1309. if test 21892 -ne `wc -c <'test.l'`; then
  1310.     echo shar: \"'test.l'\" unpacked with wrong size!
  1311. fi
  1312. # end of 'test.l'
  1313. fi
  1314. echo shar: End of archive 6 \(of 13\).
  1315. cp /dev/null ark6isdone
  1316. MISSING=""
  1317. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
  1318.     if test ! -f ark${I}isdone ; then
  1319.     MISSING="${MISSING} ${I}"
  1320.     fi
  1321. done
  1322. if test "${MISSING}" = "" ; then
  1323.     echo You have unpacked all 13 archives.
  1324.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1325. else
  1326.     echo You still need to unpack the following archives:
  1327.     echo "        " ${MISSING}
  1328. fi
  1329. ##  End of shell archive.
  1330. exit 0
  1331. -- 
  1332.  
  1333. Rich $alz            "Anger is an energy"
  1334. Cronus Project, BBN Labs    rsalz@bbn.com
  1335. Moderator, comp.sources.unix    sources@uunet.uu.net
  1336.